#pragma once
#include "Precompile.h"
#include "RenderSystem.h"

namespace Graphics{
	class DX11RenderStates;
	typedef boost::shared_ptr<DX11RenderStates> DX11RenderStatesPtr;

	class DX11RenderSystem : public RenderSystem{
	public:
		DX11RenderSystem(RenderMode &mode);
		~DX11RenderSystem();

		void initialize(HWND hwnd);
		void resetRenderSystem(RenderMode &mode);
		void saveRenderStates();
		bool restoreRenderStates();
		ID3D11DeviceContext* createDefferedContext();

		void drawIndexed(UINT IndexCount,UINT StartIndexLocation,INT BaseVertexLocation);
		void draw(UINT numVerts, UINT startLoc);
		D3D_FEATURE_LEVEL& getFeatureLevel() { return m_featureLevel; }
	private:
		void beginFrame();
		void endFrame();

		UINT getSampleCount();
		void setViewport();
		void setRasterizerState();
	private:
		ID3D11DeviceContext		*m_context;
		D3D_FEATURE_LEVEL		m_featureLevel;

		RenderTargetPtr			m_multisampledRenderTarget,
								m_renderTarget;

		ID3D11RasterizerState	*m_currentRasterizerState;

		IDXGISwapChain			*m_swapChain;

		HWND					m_hWnd;

		DX11RenderStatesPtr m_renderStates;
	protected:
		void cleanup();
	};

	class DX11RenderStates{
	public:
		DX11RenderStates():	m_inputLayout(NULL),m_DSstate(NULL),m_rState(NULL),
							m_pShader(NULL),m_vShader(NULL),m_vClsInst(NULL),
							m_pClsInst(NULL),m_cBuffer(NULL),m_sState(NULL),
							m_ref(0),m_pNumClsInst(0),m_vNumClsInst(0){}
		~DX11RenderStates(){
			if(m_inputLayout)m_inputLayout->Release();
			if(m_DSstate)m_DSstate->Release();
			if(m_rState)m_rState->Release();
			if(m_pShader)m_pShader->Release();
			if(m_vShader)m_vShader->Release();
			if(m_cBuffer)m_cBuffer->Release();
			if(m_sState)m_sState->Release();
		}

		UINT	m_ref,
				m_pNumClsInst,
				m_vNumClsInst;

		ID3D11InputLayout*		m_inputLayout;
		ID3D11DepthStencilState*m_DSstate;
		ID3D11RasterizerState*	m_rState;
		ID3D11PixelShader*		m_pShader;
		ID3D11VertexShader*		m_vShader;
		ID3D11ClassInstance*	m_vClsInst,
								*m_pClsInst;
		ID3D11Buffer*			m_cBuffer;
		ID3D11SamplerState*		m_sState;
	};

	class DX11RenderContext : public RenderContext{
	public:
		DX11RenderContext(){}
		~DX11RenderContext(){
		}

		ID3D11DeviceContext* 	m_context;
	};
}

typedef boost::shared_ptr<Graphics::DX11RenderContext> DX11RenderContextPtr;
typedef boost::shared_ptr<Graphics::DX11RenderSystem> DX11RenderSystemPtr;